package com.seer.auto.utils;

import com.seer.auto.entity.Column;
import com.seer.auto.entity.MetaEntity;
import org.apache.commons.lang3.StringUtils;

public class SqlUtils {

    public static String getJavaType(String dataType) {
        if (StringUtils.equals(dataType, "bigint")) {
            return "java.lang.Long";
        }
        if (StringUtils.equals(dataType, "char") || StringUtils.equals(dataType, "text")
            || StringUtils.startsWith(dataType, "varchar")) {
            return "java.lang.String";
        }
        if (StringUtils.contains(dataType, "int")) {
            return "java.lang.Integer";
        }
        if (StringUtils.equals(dataType, "float")) {
            return "java.lang.Float";
        }
        if (StringUtils.equals(dataType, "double")) {
            return "java.lang.Double";
        }
        if (StringUtils.equals(dataType, "decimal")) {
            return "java.math.BigDecimal";
        }
        if (StringUtils.equals(dataType, "date")) {
            return "java.sql.Date";
        }
        if (StringUtils.equals(dataType, "time")) {
            return "java.sql.Time";
        }
        if (StringUtils.equals(dataType, "datetime") || StringUtils.equals(dataType, "timestamp")) {
            return "java.sql.Timestamp";
        }
        return null;
    }

    public static String listMethod(MetaEntity<?> meta) {
        StringBuilder sb = new StringBuilder();
        sb.append("{\nString sql = \"")
            .append("SELECT ");
        for (Column c : meta.getTable().getColumns()) {
            sb.append(c.getName()).append(" as ").append(c.getJavaName()).append(", ");
        }
        sb.delete(sb.length() - 2, sb.length());
        sb.append(" FROM ").append(meta.getTable().getName())
            .append(" LIMIT ? OFFSET ?;\";\n");
        sb.append("return template.query(sql, com.seer.auto.dao.DefaultRowMapper.getRowMapper(")
            .append(meta.getClazz().getName())
            .append(".class")
            .append("), new Object[]{Integer.valueOf($2), Integer.valueOf(($1 - 1) * $2)});\n}\n");
        return sb.toString();
    }

    public static String getMethod(MetaEntity<?> meta) {
        StringBuilder sb = new StringBuilder();
        sb.append("{\nString sql = \"")
            .append("SELECT ");
        for (Column c : meta.getTable().getColumns()) {
            sb.append(c.getName()).append(" as ").append(c.getJavaName()).append(", ");
        }
        sb.delete(sb.length() - 2, sb.length());
        sb.append(" FROM ").append(meta.getTable().getName()).append(" WHERE id = ?;\";\n");
        sb.append("return template.queryForObject(sql, com.seer.auto.dao.DefaultRowMapper.getRowMapper(")
            .append(meta.getClazz().getName())
            .append(".class")
            .append("), new Object[]{Long.valueOf($1)});\n}\n");
        return sb.toString();
    }

    public static String deleteMethod(MetaEntity<?> meta) {
        StringBuilder sb = new StringBuilder();
        sb.append("{\n").append(meta.getClazz().getName()).append("\ndel = this.get($1);\n");
        sb.append("String sql = \"")
            .append("DELETE FROM ").append(meta.getTable().getName())
            .append(" WHERE id = ?;\";\n");
        sb.append("template.update(sql, new Object[]{Long.valueOf($1)});");
        sb.append("return del;\n}\n");
        return sb.toString();
    }

    public static String updateMethod(MetaEntity<?> meta) {
        StringBuilder code = new StringBuilder("{")
            .append(meta.getClazz().getName()).append(" obj = (")
            .append(meta.getClazz().getName()).append(") $2;")
            .append("java.util.List/*<String>*/ fs = new java.util.ArrayList/*<>*/();\n")
            .append("java.util.List/*<Object>*/ vs = new java.util.ArrayList/*<>*/();\n");
        for (Column c : meta.getTable().getColumns()) {
            code.append("if (obj.").append(c.getMethod()).append("() != null) {\n")
                .append("fs.add(\"").append(c.getName()).append("\");\n").append("vs.add(obj.")
                .append(c.getMethod()).append("());\n}\n");
        }
        code.append(
                "template.update(com.seer.auto.dao.DefaultPreparedStatementCreator.getDefault(Long.valueOf($1), ")
            .append("\"").append(meta.getTable().getName()).append("\", fs, vs));");
        code.append("return this.get($1);}\n");
        return code.toString();
    }

    public static String insertMethod(MetaEntity<?> meta) {
        StringBuilder code = new StringBuilder(
            "{\njava.util.List/*<String>*/ fs = new java.util.ArrayList/*<>*/();\n")
            .append(meta.getClazz().getName()).append(" obj = (")
            .append(meta.getClazz().getName()).append(") $1;")
            .append("java.util.List/*<Object>*/ vs = new java.util.ArrayList/*<>*/();\n");
        for (Column c : meta.getTable().getColumns()) {
            code.append("if (obj.").append(c.getMethod()).append("() != null) {\n")
                .append("fs.add(\"").append(c.getName()).append("\");\n").append("vs.add(obj.")
                .append(c.getMethod()).append("());\n}\n");
        }
        code.append("org.springframework.jdbc.support.KeyHolder keyHolder = new org.springframework.jdbc.support.GeneratedKeyHolder();\n");
        code.append(
                "template.update(com.seer.auto.dao.DefaultPreparedStatementCreator.getDefault(null, ")
            .append("\"").append(meta.getTable().getName()).append("\", fs, vs), keyHolder);\n");
        code.append("return this.get(keyHolder.getKey().longValue());\n}\n");
        return code.toString();
    }


    public static String countMethod(MetaEntity<?> meta) {
        StringBuilder sb = new StringBuilder("{\n")
            .append("String sql = \"SELECT COUNT(1) FROM ")
            .append(meta.getTable().getName())
            .append("\";");
        sb.append("return template.queryForObject(sql, Long.class);\n}");
        return sb.toString();
    }
}
